Seismic data section plots are visual representations that shows the amplitude of seismic data at different depths as a function of time and are used to visualize the subsurface and to identify geological features, such as faults and oil and gas reservoirs. Python is a versatile programming language that can be used to create and customize seismic data section plots, making it a great choice for seismic data visualization.
SEGY files are a standard binary file format used in the oil and gas industry for storing seismic data. They can be read and written by certain software programs, making them a convenient way to store and exchange seismic data.
For this practice coding, a SEGY file was extracted from the Volve Dataset's Seismic folder. Specifically, the SEGY file was extracted from the ST0202vsST10010_4D subdirectory, which contains data from the 4D processing of ST0202 and ST10010 (matched data).
The SEGY file was then further extracted from the Stacks subfolder, which contains raw and final stacks of the processing of the seismic survey. Take note that the selected SEGY file is a sizeable 1.13 GB.
We imported three Python libraries in this code process:
By using these libraries, we are able to enhance data operations, create attractive visualizations with ease, handle file paths and directories conveniently, and perform data interpolation in our code. This makes our code more efficient, powerful, and user-friendly.
After importing the aforementioned Python libraries, we read the SEGY file and ignores the geometric information. Thereafter, it extracts the following information from the SEGY file:
Subsequently, the code defines a regular IL and XL axis using NumPy. The il_unique and xl_unique arrays contain the unique IL and XL values in the SEGY file. The il_min, il_max, xl_min, and xl_max variables store the minimum and maximum IL and XL values.
Next, the code reorganizes the trace data into the regular grid. The d array stores the reorganized trace data.
Then, the code creates a figure for the seismic data section using Plotly. The go.Heatmap() function is used to create a heatmap of the seismic data section. The z argument to the go.Heatmap() function specifies the values to be plotted while the x argument specifies the x-axis values, and the y argument specifies the y-axis values.
# Import python libraries
import numpy as np
import plotly.graph_objects as go
import segyio
# Read the segy file
segyfile = 'ST0202ZDC12-PZ-PSDM-KIRCH-FULL-D.MIG_FIN.POST_STACK.3D.JS-017534.segy'
f = segyio.open(segyfile, ignore_geometry=True)
t = f.samples
il = f.attributes(segyio.TraceField.INLINE_3D)[:]
xl = f.attributes(segyio.TraceField.CROSSLINE_3D)[:]
traces = segyio.collect(f.trace)[:]
ntraces, nt = traces.shape
# Define a regular IL and XL axis using numpy
il_unique = np.unique(il)
xl_unique = np.unique(xl)
il_min, il_max = min(il_unique), max(il_unique)
xl_min, xl_max = min(xl_unique), max(xl_unique)
dt = t[1] - t[0]
dil = min(np.unique(np.diff(il_unique)))
dxl = min(np.unique(np.diff(xl_unique)))
# Set regular axis
ilines = np.arange(il_min, il_max + dil, dil)
xlines = np.arange(xl_min, xl_max + dxl, dxl)
nil, nxl = ilines.size, xlines.size
ilgrid, xlgrid = np.meshgrid(np.arange(nil), np.arange(nxl), indexing='ij')
# Look-up table
traces_indeces = np.full((nil, nxl), np.nan)
iils = (il - il_min) // dil
ixls = (xl - xl_min) // dxl
traces_indeces[iils, ixls] = np.arange(ntraces)
traces_available = np.logical_not(np.isnan(traces_indeces))
# Reorganize traces in regular grid
d = np.zeros((nil, nxl, nt))
d[ilgrid.ravel()[traces_available.ravel()], xlgrid.ravel()[traces_available.ravel()]] = traces
# Create figure for seismic data section
fig = go.Figure(data=go.Heatmap(z=d[nil//2].T, x=xlines, y=np.flip(t),
colorscale='RdYlBu', zmin=-5, zmax=5, zsmooth='best'))
# Update and show the plot
fig.update_layout(title='SEISMIC DATA SECTION', title_x=0.5, # Center title
width=700, height=600, autosize=False)
fig.show()